package com.autonavi.abs.common.util;

import org.apache.commons.lang3.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author wwy
 * @version V1.0
 * <p>Description: regex util</p>
 * @date 2020-07-23 14:20
 */
public class RegexUtils {

    private static Pattern HTML_UNICODE_PATTERN = Pattern.compile("&#(\\d+?);");

    private static Pattern getPattern(String regex) {
        if (regex == null) {
            return null;
        }
        return Pattern
                .compile(regex, Pattern.CASE_INSENSITIVE | Pattern.DOTALL);
    }

    /**
     * 正则表达式替换
     *
     * @param source
     * @param regex
     * @param replacement
     * @return
     */
    public static String replaceAll(String source, String regex,
                                    String replacement) {
        if (source == null || regex == null || regex.isEmpty()
                || replacement == null) {
            return source;
        }
        return getPattern(regex).matcher(source).replaceAll(replacement);
    }

    /**
     * 正则表达式替换
     *
     * @param source
     * @param regex
     * @param replacement
     * @return
     */
    public static String replaceAll(String source, String regex,
                                    String replacement, int group) {
        if (group == 0) {
            return replaceAll(source, regex, replacement);
        } else {
            Matcher m = getPattern(regex).matcher(source);
            if (m.find()) {
                String part = m.group(group);
                return source.replaceAll(part, replacement);
            }
        }
        return source;
    }

    /**
     * 是否匹配
     *
     * @param source
     * @param regex
     * @return
     */
    public static boolean match(String source, String regex) {

        if (source == null || regex == null || regex.isEmpty()) {
            return false;
        }

        Matcher matcher = getPattern(regex).matcher(source);
        return matcher.find();
    }

    /**
     * 正则表达式捕获
     *
     * @param source
     * @param regex
     * @return
     */
    public static String group(String source, String regex, int index)
            throws Exception {
        if (source == null || regex == null || regex.isEmpty()) {
            return source;
        }

        Matcher matcher = getPattern(regex).matcher(source);
        if (matcher.find()) {
            if (index <= matcher.groupCount()) {
                return matcher.group(index);
            }
        }
        return null;
    }

    /**
     * 正则表达式捕获所有匹配
     *
     * @param source
     * @param regex
     * @param index
     * @return
     * @throws Exception
     */
    public static List<String> groups(String source, String regex, int index) {
        List<String> result = new ArrayList<String>();
        if (source == null || regex == null || regex.isEmpty()) {
            return result;
        }

        Matcher matcher = getPattern(regex).matcher(source);
        while (matcher.find()) {
            if (index <= matcher.groupCount()) {
                //如果持有大量的原文本会出现内存溢出;
                //解决方法: 新建一个String持有正则匹配的片段.
                String matchedStr = new String(matcher.group(index));
                result.add(matchedStr);
            }
        }
        return result;
    }

    /**
     * 正则表达式捕获
     *
     * @param source
     * @param regex
     * @return
     */
    public static String[] groups(String source, String regex, int[] indexs) {
        if (source == null || regex == null || regex.isEmpty()
                || indexs == null || indexs.length == 0) {
            return null;
        }

        Matcher matcher = getPattern(regex).matcher(source);
        if (matcher.find()) {
            String[] result = new String[indexs.length];
            for (int i = 0; i < indexs.length; i++) {
                if (indexs[i] <= matcher.groupCount()) {
                    result[i] = matcher.group(indexs[i]);
                } else {
                    result[i] = null;
                }
            }
            return result;
        }
        return null;
    }

    /**
     * 捕获开始和结束区间的字符串
     *
     * @param source
     * @param begin
     * @param end
     * @return
     */
    public static String between(String source, String begin, String end) {
        if (source == null || source.isEmpty()) {
            return source;
        }

        Matcher matcher = null;
        int beginPos = 0;
        int endPos = source.length();
        if (begin != null && !begin.isEmpty()) {
            matcher = getPattern(begin).matcher(source);
            if (matcher.find()) {
                beginPos = matcher.end();
                if (beginPos == endPos - 1) {
                    return null;
                }
            } else {
                return null;
            }
        }
        if (end != null && !end.isEmpty()) {
            if (beginPos == 0) {
                matcher = getPattern(end).matcher(source);
            } else {
                matcher = getPattern(end).matcher(
                        source.substring(beginPos + 1));
            }
            if (matcher.find()) {
                endPos = matcher.start();
            } else {
                return null;
            }
        }
        return source.substring(beginPos + 1, endPos);
    }

    /**
     * 反转义
     *
     * @param text
     * @return
     */
    public static String unescape(String text) {
        if (text == null) {
            return null;
        }

        // HTML转义符
        text = RegexUtils.replaceAll(text, "&(quot|#34);", "\"");
        text = RegexUtils.replaceAll(text, "&(amp|#38);", "&");
        text = RegexUtils.replaceAll(text, "&(lt|#60);", "<");
        text = RegexUtils.replaceAll(text, "&(gt|#62);", ">");
        text = RegexUtils.replaceAll(text, "&(iexcl|#161);", "\\xa1");
        text = RegexUtils.replaceAll(text, "&(cent|#162);", "\\xa2");
        text = RegexUtils.replaceAll(text, "&(pound|#163);", "\\xa3");
        text = RegexUtils.replaceAll(text, "&(copy|#169);", "\\xa9");
        text = RegexUtils.replaceAll(text, "&#92;", "\\\\");
        text = RegexUtils.replaceAll(text, "&deg;", "°");
        text = RegexUtils.replaceAll(text, "&middot;", "·");

        // 处理html中以unicode表示的中文
        Matcher matcher = HTML_UNICODE_PATTERN.matcher(text);
        StringBuffer sb = new StringBuffer();
        while (matcher.find()) {
            int code = Integer.parseInt(matcher.group(1));
            char[] chars = Character.toChars(code);

            matcher.appendReplacement(sb, new String(chars));
        }
        matcher.appendTail(sb);

        return sb.toString();
    }

    private static final String realNameVerifyExp = "[\\u4e00-\\u9fa5·]{2,14}";
    private static final String idcardVerifyExp = "(^\\d{15}$)|(^\\d{18}$)|(^\\d{17}(\\d|X|x)$)";

    /**
     * 中文姓名校验
     *
     * @param realName
     * @return
     */
    public static boolean isValidRealName(String realName) {
        if (StringUtils.isEmpty(realName)) {
            return false;
        }
        return realName.matches(realNameVerifyExp);
    }

    /**
     * 身份证号校验
     *
     * @param idCard
     * @return
     */
    public static boolean isValidIdCard(String idCard) {
        if (StringUtils.isEmpty(idCard)) {
            return false;
        }
        return idCard.matches(idcardVerifyExp);
    }

}
